package cn.ljy.authority.service.impl;

import cn.ljy.authority.config.security.TokenConfig;
import cn.ljy.authority.config.upload.FileUploadConfig;
import cn.ljy.authority.dao.mapper.SysPermissionMapper;
import cn.ljy.authority.model.SysUser;
import cn.ljy.authority.model.dto.SysUserAuthority;
import cn.ljy.common.exception.model.MyServiceException;
import cn.ljy.common.exception.model.base.MyRollBackException;
import cn.ljy.common.utils.jwt.JwtUtils;
import cn.ljy.common.utils.redis.StringRedisUtils;
import cn.ljy.common.utils.requests.RequestUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 基于管理模块业务的共同类，
 */
@Service
@Validated
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor= MyRollBackException.class)
@Slf4j
public abstract class IBaseAuthService{
    @Autowired
    private StringRedisUtils stringRedisUtils;
    @Autowired
    private TokenConfig tokenConfig;

    @Autowired
    private SysPermissionMapper sysPermissionMapper;
    @Autowired
    private FileUploadConfig fileUploadConfig;

    protected boolean isSyperUser(long userId){
        boolean result=false;
        if(userId==-99){
            result=true;
        }
        return result;
    }

    /**
     * 将用户信息转化为SysUserAuthority对象
     * @param sysUser
     * @return
     */
    protected SysUserAuthority getSysUserAuthorityFromUser(SysUser sysUser){
        SysUserAuthority userAuthority=null;
        if(sysUser !=null){
            //设置图片地址为完整的网址
            sysUser.setHeadImgUrl(this.getImgWebUrl(sysUser.getHeadImgUrl()));
            //将账户对象对象转换
            userAuthority = new SysUserAuthority();
            BeanUtils.copyProperties(sysUser, userAuthority);
            //为对象赋予权限
            //List<SysRole> roles= sysUserRoleMapper.findAllRoleByUserId(sysUser.getId());
            //if(roles.contains(new SysRole(-99))){//如果用户有超级管理员权限
            if(this.isSyperUser(sysUser.getId())){//如果是超级用户
                //获取权限表的所有权限
//                SysPermisssionQuery sysPermisssionQuery=new SysPermisssionQuery();
//                sysPermisssionQuery.setEnabled(true);//只获取有权限的
                userAuthority.setSysPermissions(sysPermissionMapper.findAll(null));
            }else{
                //否则按实际拥有的权限处理
                userAuthority.setSysPermissions(sysPermissionMapper.findByUserIdAndRoleEnabled(sysUser.getId(),true));
            }
        }
        return userAuthority;
    }

    /**
     * 是否是系统用户
     * 说明：系统用户不允许删除
     * @param user
     * @return true表示是超级管理员
     */
    protected boolean isSystemUser(SysUser user){
        boolean result=false;
        if(user.getId()<=0){
            result=true;
        }
        return result;
    }


    /**
     * 获取图片的网址
     * @param fileName 文件名（不含路径）
     * @return 如果文件名为空，则返回文件名本身（也为空）
     */
    protected String getImgWebUrl(String fileName){
        String imgWebUrl=null;
        if(StringUtils.hasLength(fileName)){
            imgWebUrl= RequestUtil.getBasePath() +fileUploadConfig.getCustomerProfilePictureBaseUrl()+fileName;
        }else{
            imgWebUrl=fileName;
        }
        return imgWebUrl;
        //组装成上传头像后的网址
        //return basePath+fileUploadConfig.getCustomerProfilePictureBaseUrl()+fileName;
    }

    /**
     * 20240728使用String getUserRedisKey(String token)代替
     * 获取用户对应的key
     * @param userId 客户对象的 id
     * @return
     */
    @Deprecated
    protected String createUserRedisKeyFromUserId(long userId){
        return tokenConfig.getAccessTokenKeyHeader()+userId;
    }

    /**
     * 生成用户对应的key
     * @param token token
     * @return
     */
    protected String createUserRedisKeyFromToken(String token){
        return new StringBuilder(tokenConfig.getAccessTokenKeyHeader()).append(token).toString();
    }

    /**
     * 获取key对应的token，是生成redis的key的逆向操作
     * @param redisKey key对象
     * @return token
     */
    protected String getTokenFromRedisKey(String redisKey){
        String token=null;
        int index=redisKey.indexOf(tokenConfig.getAccessTokenKeyHeader());
        if(index>=0){
            token=redisKey.substring(index+tokenConfig.getAccessTokenKeyHeader().length());
        }else{
            throw new MyServiceException("操作失败：redis的key值格式错误");
        }
        return token;
    }

    /**
     * 保存用户信息到redis中
     * 说明：将redisKey作为key值，userAuthority转换为json字符串存到redis中的value中
     * @param redisKey
     * @param userAuthority
     */
    protected void saveTokenInRedis(String redisKey, SysUserAuthority userAuthority){
        String json= JSON.toJSONString(userAuthority);
//        SysUserAuthority sysUserAuthorityNew=JSONObject.parseObject(json);
        try{
            SysUserAuthority sysUserAuthorityNew=JSON.parseObject(json,SysUserAuthority.class);
        }catch (Exception e){
            e.printStackTrace();
        }
        stringRedisUtils.set(redisKey, JSON.toJSONString(userAuthority),tokenConfig.getExpireSeconds(), TimeUnit.SECONDS);
    }

    /**
     * 从redis中根据key值读取保存的用户信息
     * @param redisKey
     */
    protected SysUserAuthority getSysUserAuthorityFromRedis(String redisKey){
        String userAuthorityOfJson=stringRedisUtils.get(redisKey);
        return JSON.parseObject(userAuthorityOfJson,SysUserAuthority.class);
    }

    /**
     * 从token中读取保存的用户信息
     * @param token
     */
    protected SysUserAuthority getSysUserAuthorityFromToken(String token){
        String redisKey=this.createUserRedisKeyFromToken(token);
        return this.getSysUserAuthorityFromRedis(redisKey);
    }

    /**
     * 使用jwt生成用户的token
     * 说明：设计为通过jwt生成
     * @param userAuthority 对象必须要是从系统中读取
     * @return
     */
    protected String createUserToken(SysUserAuthority userAuthority) {
        //设置要携带的信息
        Map<String,Object> claims=new HashMap<>();
        claims.put("userId", userAuthority.getId());
        claims.put("username", userAuthority.getUsername());
        claims.put("nickName", userAuthority.getNickName());
        return JwtUtils.creatToken(claims,tokenConfig.getJwtSecret());//生成token
    }

}
